home *** CD-ROM | disk | FTP | other *** search
- (*===========================================================================*)
- (* Used to receive frames from TNC. Will call link change if LC frame. *)
- (* *)
- (* Copyright 1988, 1989, 1990, 1991, 1992 by H. Roy Engehausen. All *)
- (* rights reserved. *)
- (* *)
- (*===========================================================================*)
-
- UNIT BBRDATA;
-
- INTERFACE
-
- FUNCTION read_tnc_data_str : STRING;
- FUNCTION read_tnc_data_pending : BOOLEAN;
- PROCEDURE read_flush;
-
- IMPLEMENTATION
-
- USES
- DOS,
- bbconsl,
- bbdummy,
- bblc,
- bblstr,
- bbmess,
- bbmisc4,
- bbmore,
- bbsdata,
- bbsess,
- bbsrt,
- bbstr,
- bbtask,
- bbtime,
- bbtrace,
- bbwin;
-
- {$UNDEF DEBUG}
- {$UNDEF BOOBOO}
- {$UNDEF CRTIME}
-
- TYPE data_packet_result = (data_skip,
- data_present,
- timeout_because_cr,
- timeout_because_user);
-
- (*===========================================================================*)
- (* Read Data -- String format *)
- (*===========================================================================*)
-
- FUNCTION read_tnc_data_str : STRING;
-
- VAR
- bs_pos : BYTE;
- cr_found : BOOLEAN;
- cr_pos : WORD;
- cr_timeout_sw : BOOLEAN;
- cr_timeout_yes : BOOLEAN;
- i_loop : BYTE;
- read_result : data_packet_result;
- timeout_value_cr : WORD;
- timeout_value_user : WORD;
- result_str : STRING;
- this_i_data : str_mixed_ptr;
-
- (*=========================================================================*)
- (* Read Data *)
- (*=========================================================================*)
-
- FUNCTION read_tnc_data_packet : data_packet_result;
-
- VAR
- timer_on : BOOLEAN;
- timeout_for_cr : LONGINT;
- timeout_for_user : LONGINT;
-
- BEGIN;
-
- (*---------------------------------------------------------------------*)
- (* Flush any data from the sending buffers *)
- (*---------------------------------------------------------------------*)
-
- send_flush;
-
- (*---------------------------------------------------------------------*)
- (* Now we will loop looking for incoming data *)
- (*---------------------------------------------------------------------*)
-
- timer_on := FALSE;
-
- REPEAT
-
- (*-------------------------------------------------------------------*)
- (* Switch tasks just for the heck of it *)
- (*-------------------------------------------------------------------*)
-
- task_switch;
-
- (*-------------------------------------------------------------------*)
- (* Handle time expiring *)
- (*-------------------------------------------------------------------*)
-
- IF timer_on THEN
- BEGIN;
-
- (*---------------------------------------------------------------*)
- (* Main timer *)
- (*---------------------------------------------------------------*)
-
- IF (up_time > timeout_for_user) THEN
- BEGIN;
- read_tnc_data_packet := timeout_because_user;
- EXIT;
- END;
-
- (*---------------------------------------------------------------*)
- (* CR timer *)
- (*---------------------------------------------------------------*)
-
- IF (up_time > timeout_for_cr) THEN
- BEGIN;
- read_tnc_data_packet := timeout_because_cr;
- EXIT;
- END;
-
- END
-
- ELSE
-
- (*-----------------------------------------------------------------*)
- (* See if we should start timer *)
- (*-----------------------------------------------------------------*)
-
- IF send_unacked(TRUE) = 0 THEN
- BEGIN;
- timer_on := TRUE;
- timeout_for_user := up_time_from_now(timeout_value_user);
- timeout_for_cr := up_time_from_now(timeout_value_cr);
- END;
-
- (*-------------------------------------------------------------------*)
- (* Poll for incoming data *)
- (*-------------------------------------------------------------------*)
-
- send_recv_tnc(2);
-
- UNTIL NOT active_tcb^.tnc_null; (*--- End loop wait for incoming data *)
-
- timer_on := FALSE;
-
- (*---------------------------------------------------------------------*)
- (* Handle link status change *)
- (*---------------------------------------------------------------------*)
-
- IF active_tcb^.tnc_type = t_to_h_links THEN
- BEGIN;
-
- IF ((active_port^.port_type = port_modem)
- OR (active_port^.port_type = port_null_modem))
- AND active_port^.modem_dial THEN
- BEGIN;
- active_port^.modem_conn := TRUE;
- read_tnc_data_packet := data_present;
- END
- ELSE
- BEGIN;
- link_change;
- read_tnc_data_packet := data_skip;
- END;
-
- task_switch;
- EXIT;
-
- END;
-
- (*---------------------------------------------------------------------*)
- (* Watch out for other things *)
- (*---------------------------------------------------------------------*)
-
- WITH active_tcb^ DO
- IF (tnc_type <> t_to_h_conn) AND (channel <> 0) THEN
- BEGIN;
- WRITELN('RDATA');
- WRITELN('Improper response to G command on ', port_chan_s);
- WRITELN('Type was ', tnc_type);
- WRITELN('Ans was ', tnc_data.str_data);
- END;
-
- read_tnc_data_packet := data_present;
-
- END;
-
- (*=========================================================================*)
- (* Main line of read_data_string *)
- (*=========================================================================*)
-
- BEGIN;
-
- (*-----------------------------------------------------------------------*)
- (* Get local pointer *)
- (*-----------------------------------------------------------------------*)
-
- this_i_data := @active_tcb^.i_data;
-
- (*-----------------------------------------------------------------------*)
- (* Clear the more information *)
- (*-----------------------------------------------------------------------*)
-
- more_clear;
-
- (*-----------------------------------------------------------------------*)
- (* Console is special *)
- (*-----------------------------------------------------------------------*)
-
- IF active_tcb^.tcb_console THEN
- BEGIN;
- send_flush;
- operator_line;
- read_tnc_data_str := this_i_data^.str_data;
- window_write(active_tcb^.port_chan_s + '<:', this_i_data^.str_data);
- this_i_data^.str_data := '';
- this_i_data^.long_length := 0;
- EXIT;
- END;
-
- (*-----------------------------------------------------------------------*)
- (* Initialize *)
- (*-----------------------------------------------------------------------*)
-
- active_tcb^.tnc_data.long_length := 0;
- active_tcb^.tnc_data.str_data := '';
-
- timeout_value_user := active_port^.time_out;
-
- (*-----------------------------------------------------------------------*)
- (* See if we must have a timeout for a terminal mode thing *)
- (*-----------------------------------------------------------------------*)
-
- cr_timeout_sw := ((active_port^.port_type = port_modem)
- OR (active_port^.port_type = port_null_modem))
- AND (active_port^.cr_timeout <> 0);
-
- IF cr_timeout_sw THEN
- timeout_value_cr := active_port^.cr_timeout
- ELSE
- timeout_value_cr := timeout_value_user + 1;
-
- {$IFDEF CRTIME}
- trace_data('RDA1', ORD(cr_timeout_sw), NIL, '');
- trace_data('RDA2', timeout_value_cr, NIL, '');
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* See if we found a CR yet *)
- (*-----------------------------------------------------------------------*)
-
- cr_pos := l_pos(this_i_data, cr);
-
- {$IFDEF DEBUG}
- WITH active_tcb^ DO BEGIN;
- WRITELN('Start loop');
- WRITELN('Cr_pos = ', cr_pos);
- WRITELN('tnc_data =', tnc_data.long_length, '=', tnc_data.str_data);
- WRITELN('this_data =', this_i_data^.long_length,
- '=', this_i_data^.str_data);
- END;
- {$ENDIF}
-
- {$IFDEF CRTIME}
- trace_data('RDA3', cr_pos, NIL, this_i_data^.str_data);
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* If line too long for string then shorten it *)
- (*-----------------------------------------------------------------------*)
-
- IF cr_pos > 255 THEN
- cr_pos := 255;
-
- (*-----------------------------------------------------------------------*)
- (* If no CR then we wait for one *)
- (*-----------------------------------------------------------------------*)
-
- IF cr_pos = 0 THEN
- BEGIN;
-
- (*-------------------------------------------------------------------*)
- (* Flush the output buffer *)
- (*-------------------------------------------------------------------*)
-
- send_flush;
-
- (*-------------------------------------------------------------------*)
- (* Loop for CR *)
- (*-------------------------------------------------------------------*)
-
- WITH active_tcb^ DO
- REPEAT
-
- {$IFDEF DEBUG}
- WRITELN('Before read');
- WRITELN('Cr_pos = ', cr_pos);
- WRITELN('tnc_data =', tnc_data.long_length,
- '=', tnc_data.str_data);
- WRITELN('this_data =', this_i_data^.long_length,
- '=', this_i_data^.str_data);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Wait here for a packet *)
- (*---------------------------------------------------------------*)
-
- REPEAT
- read_result := read_tnc_data_packet;
-
- IF read_result = data_skip THEN
- FOR i_loop := 1 TO 20 DO
- task_switch;
- UNTIL read_result <> data_skip;
-
- (*---------------------------------------------------------------*)
- (* Kill user session on timeout *)
- (*---------------------------------------------------------------*)
-
- IF read_result = timeout_because_user THEN
- BEGIN;
- IF tcb_never_kill THEN
- read_result := timeout_because_cr
- ELSE
- timer_end_session;
- END;
-
- (*---------------------------------------------------------------*)
- (* See if we had a carriage return timeout *)
- (*---------------------------------------------------------------*)
-
- cr_timeout_yes := read_result = timeout_because_cr;
-
- (*---------------------------------------------------------------*)
- (* Debug display *)
- (*---------------------------------------------------------------*)
-
- {$IFDEF CRTIME}
- trace_data('RDA4', tnc_data.long_length, NIL, tnc_data.str_data);
- {$ENDIF}
-
- {$IFDEF DEBUG}
- WRITELN('After read');
- WRITELN('Cr_pos = ', cr_pos);
- WRITELN('tnc_data =', tnc_data.long_length,
- '=', tnc_data.str_data);
- WRITELN('this_data =', this_i_data^.long_length,
- '=', this_i_data^.str_data);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Put incoming data on end of buffer *)
- (*---------------------------------------------------------------*)
-
- l_cat(this_i_data, @tnc_data);
-
- {$IFDEF DEBUG}
- WRITELN('After cat ');
- WRITELN('Cr_pos = ', cr_pos);
- WRITELN('tnc_data =', tnc_data.long_length,
- '=', tnc_data.str_data);
- WRITELN('this_data =', this_i_data^.long_length,
- '=', this_i_data^.str_data);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Any CR in sight? *)
- (*---------------------------------------------------------------*)
-
- cr_pos := l_pos(this_i_data, cr);
-
- {$IFDEF DEBUG}
- WRITELN('After pos ');
- WRITELN('Cr_pos = ', cr_pos);
- {$ENDIF}
-
- (*---------------------------------------------------------------*)
- (* Force fake end if more than one string worth *)
- (*---------------------------------------------------------------*)
-
- cr_found := cr_pos <> 0;
- IF cr_pos > 255 THEN
- BEGIN;
- cr_pos := 255;
- cr_found := FALSE;
- END;
-
- (*---------------------------------------------------------------*)
- (* Handle timeout for carriage return *)
- (*---------------------------------------------------------------*)
-
- IF cr_timeout_yes AND (cr_pos = 0) THEN
- BEGIN;
- cr_pos := this_i_data^.long_length;
- IF cr_pos = 0 THEN
- BEGIN;
- read_tnc_data_str := '';
- {$IFDEF CRTIME}
- trace_data('RDA5', 0, NIL, '');
- {$ENDIF}
- EXIT;
- END;
- END;
-
- (*---------------------------------------------------------------*)
- (* If too long then force a CR anyway *)
- (*---------------------------------------------------------------*)
-
- IF NOT cr_found THEN
- BEGIN;
- IF this_i_data^.long_length > 255 THEN
- cr_pos := 255
- ELSE
- IF tnc_data.long_length > 0 THEN
- cr_pos := this_i_data^.long_length;
- END;
-
- UNTIL cr_pos <> 0; (*----- End of search for CR loop --------------*)
-
- END; (*----- End of code when no CR in buffer -------------------------*)
-
- (*-----------------------------------------------------------------------*)
- (* Check for booboo *)
- (*-----------------------------------------------------------------------*)
-
- {$IFDEF BOOBOO}
- IF cr_pos > 255 THEN
- WITH active_tcb^ DO
- BEGIN;
- WRITELN('Invalid packet size in RDATA');
- WRITELN('Cr_pos = ', cr_pos);
- WRITELN('tnc_data =', tnc_data.long_length,
- '=', tnc_data.str_data);
- WRITELN('this_data =', this_i_data^.long_length,
- '=', this_i_data^.str_data);
- HALT;
- END;
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Get result *)
- (*-----------------------------------------------------------------------*)
-
- result_str := substr(this_i_data^.str_data, 1, cr_pos);
-
- (*-----------------------------------------------------------------------*)
- (* Skip the CR *)
- (*-----------------------------------------------------------------------*)
-
- INC(cr_pos);
-
- (*-----------------------------------------------------------------------*)
- (* Check for booboo *)
- (*-----------------------------------------------------------------------*)
-
- {$IFDEF BOOBOO}
- IF i > 256 THEN
- BEGIN;
- WRITELN('RDATA');
- WRITELN('Suspect packet break position -- ', cr_pos);
- WRITELN('IDATA = ', active_tcb^.i_data.long_length);
- WRITELN('TNC DATA = ', active_tcb^.tnc_data.long_length);
- cr_pos := 256;
- END;
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* Move up any data remaining and concatenate old data *)
- (*-----------------------------------------------------------------------*)
-
- active_tcb^.i_data := l_substr(@active_tcb^.i_data, cr_pos, 0)^;
- IF active_tcb^.tnc_data.long_length > 0 THEN
- l_cat(@active_tcb^.i_data, @active_tcb^.tnc_data);
-
- (*-----------------------------------------------------------------------*)
- (* Check for booboo *)
- (*-----------------------------------------------------------------------*)
-
- {$IFDEF BOOBOO}
- WITH active_tcb^ DO
- IF tnc_data.long_length > 0 THEN
- BEGIN;
- WRITELN('Lost incoming data packet');
- WRITELN('TDATA =', tnc_data.long_length, ' = ', tnc_data.str_data);
- WRITELN('IDATA =', i_data.long_length, ' = ', i_data.str_data);
- WRITELN('RDATA =', LENGTH(result_str), ' = ', result_str);
- END;
- {$ENDIF}
-
- (*-----------------------------------------------------------------------*)
- (* If modem then handle backspaces *)
- (*-----------------------------------------------------------------------*)
-
- IF ((active_port^.port_type = port_modem)
- OR (active_port^.port_type = port_null_modem))
- AND NOT active_tcb^.tcb_binary THEN
- BEGIN;
-
- bs_pos := POS(bs, result_str);
-
- WHILE bs_pos <> 0 DO
- BEGIN;
-
- i_loop := LENGTH(result_str) - bs_pos;
-
- IF (bs_pos <> 1) AND (i_loop > 0) THEN
- BEGIN;
-
- MOVE(result_str[bs_pos+1], result_str[bs_pos-1], i_loop);
-
- DEC(BYTE(result_str[0]));
-
- END
- ELSE
- IF i_loop > 0 THEN
- MOVE(result_str[bs_pos+1], result_str[bs_pos], i_loop);
-
- DEC(BYTE(result_str[0]));
-
- bs_pos := POS(bs, result_str);
-
- END; (*----- End loop for backspaces -------------------------------*)
-
- END; (*----- End backspace handler -------------------------------------*)
-
- (*-----------------------------------------------------------------------*)
- (* Show incoming line *)
- (*-----------------------------------------------------------------------*)
-
- window_write(active_tcb^.port_chan_s + '<:', result_str);
-
- (*-----------------------------------------------------------------------*)
- (* Set result *)
- (*-----------------------------------------------------------------------*)
-
- read_tnc_data_str := result_str;
-
- END;
-
- (*===========================================================================*)
- (* Read Data Pending *)
- (*===========================================================================*)
-
- FUNCTION read_tnc_data_pending : BOOLEAN;
-
- VAR
- i: WORD;
- j: WORD;
-
- BEGIN;
-
- j := active_tcb^.i_data.long_length;
- IF active_tcb^.tcb_binary THEN
- read_tnc_data_pending := j <> 0
- ELSE
- BEGIN;
- i := l_pos(@active_tcb^.i_data, cr);
- read_tnc_data_pending := (i <> 0) OR (j >= 255);
- END;
-
- END;
-
- (*===========================================================================*)
- (* Read Flush *)
- (*===========================================================================*)
-
- PROCEDURE read_flush;
- BEGIN;
-
- WHILE TRUE DO
- WITH active_tcb^ DO
- BEGIN;
-
- task_switch;
-
- send_recv_tnc(2);
-
- IF tnc_null THEN EXIT;
-
- IF tnc_type = t_to_h_links THEN
- BEGIN;
- link_change;
- task_switch;
- END
- ELSE
- IF (tnc_type <> t_to_h_conn) AND (channel <> 0) THEN
- BEGIN;
- WRITELN('RFLUSH');
- WRITELN('Improper response to G command on ', port_chan_s);
- WRITELN('Type was ', tnc_type);
- WRITELN('Ans was ', tnc_data.str_data);
- END;
- END;
-
- END;
-
- END.